<template>
  <div class="menu-permissions">
    <div class="permission-header">
      <h3>页面权限</h3>
      <div class="header-controls">
        <span class="label">菜单列表</span>
        <el-checkbox 
          v-model="selectAll" 
          :indeterminate="isIndeterminate"
          @change="(val: any) => handleSelectAll(val)"
        >
          全选
        </el-checkbox>
      </div>
    </div>
    
    <div class="menu-tree-container">
      <el-tree
        ref="treeRef"
        :data="menuTree"
        :props="treeProps"
        :default-checked-keys="checkedKeys"
        :default-expanded-keys="expandedKeys"
        show-checkbox
        node-key="id"
        @check="handleCheck"
      >
        <template #default="{ data }">
          <span class="tree-node" :class="{ 'disabled-node': data.disabled }">
            <el-icon v-if="data.icon" class="node-icon">
              <component :is="data.icon" />
            </el-icon>
            <span class="node-label">{{ data.label }}</span>
            <span v-if="data.disabled" class="disabled-tag">（默认）</span>
          </span>
        </template>
      </el-tree>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, markRaw } from 'vue'
import { ElTree, ElCheckbox, ElIcon } from 'element-plus'
import { 
  VideoPlay, MapLocation, Camera, VideoPause, Menu, 
  OfficeBuilding, UserFilled, Setting, VideoCamera, Bell, Monitor, User
} from '@element-plus/icons-vue'
import { MENU_PERMISSIONS, type PagePermission } from '@/types'

// Props
interface Props {
  modelValue: string[]
  menuData?: any[]
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  menuData: () => []
})

// Emits
const emit = defineEmits<{
  'update:modelValue': [value: string[]]
}>()

// 响应式数据
const treeRef = ref()
const checkedKeys = ref<string[]>([])
const expandedKeys = ref<string[]>([])

// 树形组件配置
const treeProps = {
  children: 'children',
  label: 'label'
}

// 图标映射
const iconMap: Record<string, any> = {
  VideoPlay: markRaw(VideoPlay),
  MapLocation: markRaw(MapLocation),
  Camera: markRaw(Camera),
  VideoPause: markRaw(VideoPause),
  Menu: markRaw(Menu),
  OfficeBuilding: markRaw(OfficeBuilding),
  UserFilled: markRaw(UserFilled),
  Setting: markRaw(Setting),
  VideoCamera: markRaw(VideoCamera),
  Bell: markRaw(Bell),
  Monitor: markRaw(Monitor),
  User: markRaw(User)
}

// 将菜单权限配置转换为树形结构
const convertToTreeData = (permissions: PagePermission[]): any[] => {
  return permissions
    .filter(permission => permission.isConfigurable !== false) // 过滤掉不可配置的节点
    .map(permission => {
      const node: any = {
        id: permission.id,
        label: permission.name,
        icon: iconMap[permission.icon] || Setting,
        path: permission.path,
        disabled: permission.disabled || false,
        isConfigurable: permission.isConfigurable || false
      }
      
      if (permission.code) {
        node.code = permission.code
      }
      
      if (permission.children) {
        // 递归过滤子节点
        node.children = convertToTreeData(permission.children)
      }
      
      return node
    })
}

const menuTree = ref(convertToTreeData(MENU_PERMISSIONS))

// 计算属性
const selectAll = computed({
  get: () => {
    const allKeys = getAllNodeKeys(menuTree.value)
    // 全选状态：所有节点都被选中（包括禁用的）
    return allKeys.length > 0 && checkedKeys.value.length === allKeys.length
  },
  set: (value: boolean) => {
    if (value) {
      // 全选时选中所有节点（包括禁用的）
      checkedKeys.value = getAllNodeKeys(menuTree.value)
    } else {
      // 取消全选时只保留禁用的节点
      const disabledKeys = getDisabledNodeKeys(menuTree.value)
      checkedKeys.value = disabledKeys
    }
    updateTreeChecked()
  }
})

const isIndeterminate = computed(() => {
  const allKeys = getAllNodeKeys(menuTree.value)
  const configurableKeys = getAllConfigurableNodeKeys(menuTree.value)
  
  // 如果所有可配置的节点都被选中，但不是全选状态，则为半选状态
  const selectedConfigurableKeys = checkedKeys.value.filter(key => 
    configurableKeys.includes(key)
  )
  
  return selectedConfigurableKeys.length > 0 && 
         selectedConfigurableKeys.length < configurableKeys.length &&
         checkedKeys.value.length < allKeys.length
})

// 获取所有可配置的节点键值
const getAllConfigurableNodeKeys = (nodes: any[]): string[] => {
  let keys: string[] = []
  nodes.forEach(node => {
    // 只添加可配置的节点
    if (node.isConfigurable) {
      keys.push(node.id)
    }
    if (node.children) {
      keys = keys.concat(getAllConfigurableNodeKeys(node.children))
    }
  })
  return keys
}

// 获取所有节点键值（包括禁用的）
const getAllNodeKeys = (nodes: any[]): string[] => {
  let keys: string[] = []
  nodes.forEach(node => {
    keys.push(node.id)
    if (node.children) {
      keys = keys.concat(getAllNodeKeys(node.children))
    }
  })
  return keys
}

// 获取所有禁用的节点键值
const getDisabledNodeKeys = (nodes: any[]): string[] => {
  let keys: string[] = []
  nodes.forEach(node => {
    if (node.disabled) {
      keys.push(node.id)
    }
    if (node.children) {
      keys = keys.concat(getDisabledNodeKeys(node.children))
    }
  })
  return keys
}

// 处理全选
const handleSelectAll = (checked: boolean) => {
  if (checked) {
    // 全选时选中所有节点（包括禁用的）
    checkedKeys.value = getAllNodeKeys(menuTree.value)
  } else {
    // 取消全选时只保留禁用的节点
    const disabledKeys = getDisabledNodeKeys(menuTree.value)
    checkedKeys.value = disabledKeys
  }
  updateTreeChecked()
  emitUpdate()
}

// 处理节点选择
const handleCheck = (checkedData: any, checked: any) => {
  // 获取当前选中的节点
  const currentCheckedKeys = checked.checkedKeys
  
  // 处理父子节点联动
  const newCheckedKeys = handleParentChildSelection(checkedData, currentCheckedKeys)
  
  checkedKeys.value = newCheckedKeys
  emitUpdate()
}

// 处理父子节点联动选择
const handleParentChildSelection = (checkedData: any, currentCheckedKeys: string[]): string[] => {
  const newCheckedKeys = [...currentCheckedKeys]
  
  // 如果选中的是父节点
  if (checkedData.children && checkedData.children.length > 0) {
    const isChecked = currentCheckedKeys.includes(checkedData.id)
    
    if (isChecked) {
      // 选中父节点时，选中所有子节点
      const childKeys = getAllChildKeys(checkedData)
      childKeys.forEach(key => {
        if (!newCheckedKeys.includes(key)) {
          newCheckedKeys.push(key)
        }
      })
    } else {
      // 取消选中父节点时，取消选中所有子节点
      const childKeys = getAllChildKeys(checkedData)
      childKeys.forEach(key => {
        const index = newCheckedKeys.indexOf(key)
        if (index > -1) {
          newCheckedKeys.splice(index, 1)
        }
      })
    }
  }
  
  // 如果选中的是子节点，检查是否需要更新父节点状态
  const parentNode = findParentNode(menuTree.value, checkedData.id)
  if (parentNode) {
    const allChildKeys = getAllChildKeys(parentNode)
    const checkedChildKeys = allChildKeys.filter(key => newCheckedKeys.includes(key))
    
    if (checkedChildKeys.length === allChildKeys.length) {
      // 所有子节点都被选中，选中父节点
      if (!newCheckedKeys.includes(parentNode.id)) {
        newCheckedKeys.push(parentNode.id)
      }
    } else if (checkedChildKeys.length === 0) {
      // 没有子节点被选中，取消选中父节点
      const index = newCheckedKeys.indexOf(parentNode.id)
      if (index > -1) {
        newCheckedKeys.splice(index, 1)
      }
    }
    // 如果部分子节点被选中，父节点保持半选状态（由Element Plus自动处理）
  }
  
  return newCheckedKeys
}

// 获取节点的所有子节点键值
const getAllChildKeys = (node: any): string[] => {
  let keys: string[] = []
  if (node.children) {
    node.children.forEach((child: any) => {
      keys.push(child.id)
      keys = keys.concat(getAllChildKeys(child))
    })
  }
  return keys
}

// 查找父节点
const findParentNode = (nodes: any[], targetId: string): any => {
  for (const node of nodes) {
    if (node.children) {
      for (const child of node.children) {
        if (child.id === targetId) {
          return node
        }
        const found = findParentNode([child], targetId)
        if (found) {
          return found
        }
      }
    }
  }
  return null
}

// 更新树形组件的选中状态
const updateTreeChecked = () => {
  if (treeRef.value) {
    treeRef.value.setCheckedKeys(checkedKeys.value)
  }
}

// 发出更新事件
const emitUpdate = () => {
  emit('update:modelValue', checkedKeys.value)
}

// 监听器已移到下面，处理权限码为-1的情况

// 组件挂载时设置展开的节点和默认选中的禁用节点
onMounted(() => {
  expandedKeys.value = menuTree.value.map(node => node.id)
  
  // 默认选中禁用的节点
  const disabledKeys = getDisabledNodeKeys(menuTree.value)
  if (disabledKeys.length > 0) {
    checkedKeys.value = [...checkedKeys.value, ...disabledKeys]
    updateTreeChecked()
  }
})

// 监听props变化，处理权限码为-1的情况
watch(
  () => props.modelValue,
  (newValue) => {
    if (newValue && newValue.length > 0) {
      // 检查是否包含所有可配置的权限（表示权限码为-1）
      const configurableKeys = getAllConfigurableNodeKeys(menuTree.value)
      const allConfigurableSelected = configurableKeys.every(key => newValue.includes(key))
      
      if (allConfigurableSelected) {
        // 如果选中了所有可配置权限，同时选中所有节点（包括禁用的）
        const allKeys = getAllNodeKeys(menuTree.value)
        checkedKeys.value = allKeys
      } else {
        checkedKeys.value = newValue || []
      }
    } else {
      // 即使没有权限数据，也要保留禁用的节点
      const disabledKeys = getDisabledNodeKeys(menuTree.value)
      checkedKeys.value = disabledKeys
    }
    updateTreeChecked()
  },
  { immediate: true }
)
</script>

<style scoped>
.menu-permissions {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.permission-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #e4e7ed;
}

.permission-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.label {
  font-size: 14px;
  color: #606266;
}

.menu-tree-container {
  flex: 1;
  overflow-y: auto;
  padding-right: 8px;
}

.tree-node {
  display: flex;
  align-items: center;
  gap: 6px;
}

.node-icon {
  font-size: 14px;
  color: #606266;
}

.node-label {
  font-size: 14px;
  color: #303133;
}

:deep(.el-tree-node__content) {
  height: 32px;
  padding: 0 8px;
}

:deep(.el-tree-node__content:hover) {
  background-color: #f5f7fa;
}

:deep(.el-checkbox) {
  margin-right: 8px;
}

.disabled-node {
  color: #909399;
}

.disabled-tag {
  font-size: 12px;
  color: #909399;
  margin-left: 4px;
}

:deep(.el-tree-node__content) {
  position: relative;
}

:deep(.el-tree-node__content .el-checkbox) {
  pointer-events: auto;
}

:deep(.el-tree-node__content .disabled-node .el-checkbox) {
  pointer-events: none;
}

:deep(.el-tree-node__content .disabled-node .el-checkbox .el-checkbox__input) {
  cursor: not-allowed;
}
</style>
